﻿using Microsoft.Web.Infrastructure.DynamicModuleHelper;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using System.Web.Routing;
using System.Web.Mvc;

using ERPStore.Extensions;
using ERPStore.Web.Extensions;
using ERPStore.Web.Routing;

using Owin;

using Microsoft.Practices.Unity;

namespace ERPStore.Web
{
	public class ERPStoreStartup
	{
		public static bool m_IsInitialized = false;

		internal static void Init(System.Web.HttpContext ctx)
		{
			try
			{
				var httpContext = new System.Web.HttpContextWrapper(ctx);
				var executingContext = ERPStore.Configuration.ConfigurationSettings.AppSettings["executingContext"] ?? "Production";
				var ec = (ERPStore.Models.ExecutingContext)Enum.Parse(typeof(ERPStore.Models.ExecutingContext), executingContext, true);

				Register(httpContext, ec);
			}
			catch (Exception ex)
			{
				GlobalConfiguration.Configuration.FailedOnInitialize = true;
				GlobalConfiguration.Configuration.FirstError = ex;
				if (!ctx.Request.IsLocal)
				{
					System.Diagnostics.EventLog.WriteEntry("Application", ex.ToString(), System.Diagnostics.EventLogEntryType.Error);
				}
				else
				{
					if (System.Web.Routing.RouteTable.Routes.GetByName("CatchAll") == null)
					{
						System.Web.Routing.RouteTable.Routes.MapERPStoreRoute(
							"CatchAll"
							, "{*catchall}"
							, new { controller = "Home", action = "CatchAll" }
						);
					}
					throw;
				}
			}
		}

		internal static void Register(System.Web.HttpContextBase ctx, ERPStore.Models.ExecutingContext executingContext)
		{
			if (m_IsInitialized)
			{
				return;
			}

			ERPStore.GlobalConfiguration.Configuration.HosterName = ERPStore.Configuration.ConfigurationSettings.AppSettings["ERStoreHostName"] ?? "WebApp";
			ERPStore.GlobalConfiguration.Configuration.ExecutingContext = executingContext;
			var section = (System.Web.Configuration.CompilationSection)System.Configuration.ConfigurationManager.GetSection("system.web/compilation");
			ERPStore.GlobalConfiguration.Configuration.DebugEnabled = section.Debug;
			GlobalConfiguration.Configuration.Logger.Info("initialization started");
			if (GlobalConfiguration.Configuration.ExecutingContext == ERPStore.Models.ExecutingContext.Production
				&& GlobalConfiguration.Configuration.DebugEnabled)
			{
				GlobalConfiguration.Configuration.Logger.Notification("Debug enabled in production !");
			}
			GlobalConfiguration.Configuration.Logger.Info("ERPStore ExecutionContext {0}", GlobalConfiguration.Configuration.ExecutingContext);
			Microsoft.Practices.Unity.IUnityContainer container = null;
			if (GlobalConfiguration.Configuration.ExecutingContext == ERPStore.Models.ExecutingContext.Test)
			{
				Web.Start.UnityWebActivator.Start();
			}
			container = ERPStore.Web.Start.UnityConfig.GetConfiguredContainer(ctx);
			ERPStore.Web.Start.MappingConfig.Register();
			ERPStore.Web.Start.SiteConfig.Configure(container, ctx);
			if (GlobalConfiguration.Configuration.ExecutingContext == ERPStore.Models.ExecutingContext.Test)
			{
				ERPStore.Web.Start.WebApiConfig.Register(System.Web.Http.GlobalConfiguration.Configuration);
			}
			else
			{
				System.Web.Http.GlobalConfiguration.Configure(ERPStore.Web.Start.WebApiConfig.Register);
			}
			
			ERPStore.Web.Start.ValidationConfig.Register(container);
			ERPStore.Web.Start.PluginsConfig.Load(container, ctx);
			ERPStore.Web.Start.EventBrokerConfig.Register(container);
			ERPStore.Web.Start.FilterConfig.RegisterGlobalFilters(System.Web.Mvc.GlobalFilters.Filters);
			ERPStore.Web.Start.RouteConfig.RegisterRoutes(System.Web.Routing.RouteTable.Routes, container);
			ERPStore.Web.Start.MetadataConfig.Configure(container);
			ERPStore.Web.Start.BundleConfig.Register(ctx);

			if (GlobalConfiguration.Configuration.ExecutingContext != ERPStore.Models.ExecutingContext.Preproduction)
			{
				GlobalConfiguration.Configuration.Logger.Debug("Registered services list : ");
				// Show services list
				foreach (var item in container.Registrations)
				{
					GlobalConfiguration.Configuration.Logger.Debug("Service {0} : {1} mappedTo {2}", item.Name, item.RegisteredType, item.MappedToType);
					GlobalConfiguration.Configuration.Logger.Debug("Lifetime : {0}", item.LifetimeManagerType);
				}
			}

			ViewEngines.Engines.Add(new Mail.EmailerViewEngine());

			var eventPublisher = container.Resolve<EventBrokR.IPublisher>();
			eventPublisher.PublishAsync(new ERPStore.Events.ApplicationStartedEvent());

			GlobalConfiguration.Configuration.Logger.Info("initialization completed");
			GlobalConfiguration.Configuration.Logger.Notification("ERPStore for {0} ({1}) in {2} is started context {3} debug {4}", GlobalConfiguration.Configuration.Settings.SiteName, GlobalConfiguration.Configuration.Settings.ApplicationName, System.Environment.MachineName, GlobalConfiguration.Configuration.ExecutingContext, GlobalConfiguration.Configuration.DebugEnabled);

			m_IsInitialized = true;
		}
	}
}
